#include "qedalibrary.h"
#include "qedacomponent.h"
#include "librarytreeitem.h"

#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qtextstream.h>
#include <QtGui/qfont.h>
#include <QtGui/qmdiarea.h>
#include <QtGui/qmdisubwindow.h>
#include <QtXml/qdom.h>

QedaLibrary::QedaLibrary(QObject *parent) :
    QObject(parent)
{
    m_modified = false;
}

QedaLibrary::~QedaLibrary()
{
    qDeleteAll(m_components);
    foreach (int i, m_treeItem.keys())
        if (m_treeItem[i])
            delete m_treeItem[i];
}

void QedaLibrary::addComponent(QedaComponent *component)
{
    //m_components.append(component);
    appendComponent(component);
    emit componentsAdded(this, QList<QedaComponent*>() << component);
    setModified(true);
}

void QedaLibrary::addGroup(const QString &group)
{
    if (m_groups.contains(group))
        ++m_groups[group];
    else
        m_groups.insert(group, 1);
}

void QedaLibrary::addReference(const QString &ref)
{
    if (m_references.contains(ref))
        ++m_references[ref];
    else
        m_references.insert(ref, 1);
}


void QedaLibrary::appendComponent(QedaComponent *component)
{
    m_components.append(component);
    addReference(component->reference());
    addGroup(component->group());
}

QedaComponent *QedaLibrary::createComponent()
{
    QedaComponent *component = newComponent();
    return component;
}

QStringList QedaLibrary::groups()
{
    QStringList gs = m_groups.keys();
    qSort(gs);
    return gs;
}

bool QedaLibrary::load(const QString &filePath)
{
    QDomDocument qlib("qlib");
    QFile qlibFile(filePath);
    if (!qlibFile.open(QIODevice::ReadOnly))
         return false;
    if (!qlib.setContent(&qlibFile))
    {
         qlibFile.close();
         return false;
    }
    qlibFile.close();
    QDomElement root = qlib.documentElement();
    if (root.tagName() != "qlib")
        return false;
    m_path = filePath;
    if (root.hasAttribute("name"))
        m_name = root.attribute("name");

    m_components.clear();
    QDomNode n = root.firstChild();
    while(!n.isNull())
    {
        QDomElement e = n.toElement();
        if(!e.isNull())
        {
            if (e.tagName() == "comp")
            {
                QedaComponent *component = newComponent();
                component->fromXml(e);
                appendComponent(component);
                //m_components.append(component);
            }
        }
        n = n.nextSibling();
    }
    return true;
}

QedaComponent *QedaLibrary::newComponent()
{
    QedaComponent *newComponent = new QedaComponent(this);
    connect(newComponent, SIGNAL(componentUpdated(QedaComponent*)),
            this, SIGNAL(componentUpdated(QedaComponent*)));
    return newComponent;
}

QStringList QedaLibrary::references()
{
    QStringList refs = m_references.keys();
    qSort(refs);
    return refs;
}

void QedaLibrary::removeAll()
{

}

bool QedaLibrary::removeComponent(QedaComponent *component)
{
    bool isOk = m_components.removeOne(component);
    component->closeWin(true);
    removeReference(component->reference());
    removeGroup(component->group());
    emit componentRemoved(component);
    setModified(true);
    return isOk;
}

void QedaLibrary::removeGroup(const QString &group)
{
    if (m_groups.contains(group) && m_groups[group] > 0)
    {
        --m_groups[group];
        if (!m_groups[group])
            m_groups.remove(group);
    }
}

void QedaLibrary::removeReference(const QString &ref)
{
    if (m_references.contains(ref) && m_references[ref] > 0)
    {
        --m_references[ref];
        if (!m_references[ref])
            m_references.remove(ref);
    }
}

bool QedaLibrary::save()
{
    if (!m_modified)
        return true;
    QDomDocument qlib("qlib");
    QDomProcessingInstruction process = qlib.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
    qlib.appendChild(process);

    QDomElement root = qlib.createElement("qlib");
    root.setAttribute("rev", "1");
    root.setAttribute("name", m_name);
    qlib.appendChild(root);

    for (int i = 0; i < m_components.count(); ++i)
    {
        QDomElement component = qlib.createElement("comp");
        m_components.at(i)->toXml(qlib, component);
        root.appendChild(component);
    }

    QFile qlibFile(m_path);
    bool isOk = false;
    if (qlibFile.open(QFile::WriteOnly | QFile::Truncate))
    {
        QTextStream qlibStream(&qlibFile);
        qlibStream << qlib.toString();
        qlibFile.close();
        isOk = true;
        for (int i = 0; i < m_components.count(); ++i)
            m_components.at(i)->setModified(false);
        setModified(false);
    }
    return isOk;
}

void QedaLibrary::setModified(bool modified)
{
    if (m_modified != modified)
    {
        m_modified = modified;
        foreach (int i, m_treeItem.keys())
        {
            QFont myFont = m_treeItem[i]->font(0);
            myFont.setBold(modified);
            m_treeItem[i]->setFont(0, myFont);
        }
    }
}

void QedaLibrary::updateGroups(const QString &oldGroup, const QString &newGroup)
{
    removeGroup(oldGroup);
    addGroup(newGroup);
}

void QedaLibrary::updateReferences(const QString &oldRef, const QString &newRef)
{
    removeReference(oldRef);
    addReference(newRef);
}
